/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.domain.IsfdDatasourceConfiguration;
import com.comac.ins.isfd.domain.bo.IsfdDatasourceConfigurationBo;
import com.comac.ins.isfd.domain.bo.IsfdDatasourceConfigurationQueryBo;
import com.comac.ins.isfd.domain.vo.IsfdDatasourceConfigurationVo;
import com.comac.ins.isfd.mapper.IsfdDatasourceConfigurationMapper;
import com.comac.ins.isfd.service.IIsfdDatasourceConfigurationService;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.Collection;

/**
 * 数据源配置Service业务层处理
 *
 * @author Lion Li
 * @date 2024-10-10
 */

@Slf4j
@RequiredArgsConstructor
@Service
public class IsfdDatasourceConfigurationServiceImpl implements IIsfdDatasourceConfigurationService {
    @Autowired
    private IsfdDatasourceConfigurationMapper baseMapper;

    /**
     * 查询数据源配置
     *
     * @param id 主键
     * @return 数据源配置
     */
    @Override
    public IsfdDatasourceConfigurationVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询数据源配置列表
     *
     * @param bo 查询条件
     * @return 数据源配置分页列表
     */
    @Override
    public TableDataInfo<IsfdDatasourceConfigurationVo> queryPageList(IsfdDatasourceConfigurationQueryBo bo) {
        LambdaQueryWrapper<IsfdDatasourceConfiguration> lqw = buildQueryWrapper(bo);
        lqw.eq(IsfdDatasourceConfiguration::getIsDeleted, 0);
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageSize(bo.getPageSize());
        pageQuery.setPageNum(bo.getPageNum());
        Page<IsfdDatasourceConfigurationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

//    /**
//     * 查询符合条件的数据源配置列表
//     *
//     * @param bo 查询条件
//     * @return 数据源配置列表
//     */
//    @Override
//    public List<IsfdDatasourceConfigurationVo> queryList(IsfdDatasourceConfigurationBo bo) {
//        LambdaQueryWrapper<IsfdDatasourceConfiguration> lqw = buildQueryWrapper(bo);
//        return baseMapper.selectVoList(lqw);
//    }


    private LambdaQueryWrapper<IsfdDatasourceConfiguration> buildQueryWrapper(IsfdDatasourceConfigurationQueryBo bo) {
        //Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IsfdDatasourceConfiguration> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getDataSourceType()), IsfdDatasourceConfiguration::getDataSourceType, bo.getDataSourceType());
        lqw.like(StringUtils.isNotBlank(bo.getDataSourceName()), IsfdDatasourceConfiguration::getDataSourceName, bo.getDataSourceName());
//        lqw.eq(StringUtils.isNotBlank(bo.getDataSourceDescriptive()), IsfdDatasourceConfiguration::getDataSourceDescriptive, bo.getDataSourceDescriptive());
//        lqw.eq(StringUtils.isNotBlank(bo.getUrl()), IsfdDatasourceConfiguration::getUrl, bo.getUrl());
//        lqw.like(StringUtils.isNotBlank(bo.getUserName()), IsfdDatasourceConfiguration::getUserName, bo.getUserName());
//        lqw.eq(StringUtils.isNotBlank(bo.getSecretCode()), IsfdDatasourceConfiguration::getSecretCode, bo.getSecretCode());
//        lqw.eq(StringUtils.isNotBlank(bo.getRequestType()), IsfdDatasourceConfiguration::getRequestType, bo.getRequestType());
//        lqw.eq(StringUtils.isNotBlank(bo.getDefaultRequestHeader()), IsfdDatasourceConfiguration::getDefaultRequestHeader, bo.getDefaultRequestHeader());
//        lqw.eq(StringUtils.isNotBlank(bo.getRequestParameters()), IsfdDatasourceConfiguration::getRequestParameters, bo.getRequestParameters());
//        lqw.eq(StringUtils.isNotBlank(bo.getProtoco()), IsfdDatasourceConfiguration::getProtoco, bo.getProtoco());
//        lqw.eq(StringUtils.isNotBlank(bo.getStorageLocation()), IsfdDatasourceConfiguration::getStorageLocation, bo.getStorageLocation());
//        lqw.eq(bo.getIsDeleted() != null, IsfdDatasourceConfiguration::getIsDeleted, bo.getIsDeleted());
        return lqw;
    }

    /**
     * 新增数据源配置
     *
     * @param bo 数据源配置
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(IsfdDatasourceConfigurationBo bo) {
        IsfdDatasourceConfiguration add = MapstructUtils.convert(bo, IsfdDatasourceConfiguration.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
//        if (flag) {
//            bo.setId(add.getId());
//        }
        return flag;
    }

    /**
     * 修改数据源配置
     *
     * @param bo 数据源配置
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(IsfdDatasourceConfigurationBo bo) {
        IsfdDatasourceConfiguration update = MapstructUtils.convert(bo, IsfdDatasourceConfiguration.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IsfdDatasourceConfiguration entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除数据源配置信息
     *
     * @param ids 待删除的主键集合
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {

        for (Long DatasourceConfId : ids) {
            baseMapper.deleteById(DatasourceConfId);
        }
        //TODO 做一些业务上的校验,判断是否需要校验

        return Boolean.TRUE;
    }

    @Override
    public Boolean testByBo(IsfdDatasourceConfigurationBo bo) {

        String url = bo.getUrl();
        //String url = "jdbc:mysql://172.16.41.117:3306";
        String userName = bo.getUserName();
        //String userName = "root";
        String secretCode = bo.getSecretCode();
        //String secretCode = "C0m@c@2025";
        String requestType = bo.getRequestType();
        String defaultRequestHeader = bo.getDefaultRequestHeader();
        String requestParameters = bo.getRequestParameters();
        String dataSourceType = bo.getDataSourceType();
        String dataSourceName = bo.getDataSourceName();

        if (dataSourceType.equals("MySQL") || dataSourceType.equals("Oracle") || dataSourceType.equals("Doris")) {
            String connectionStr = String.format("jdbc:mysql://%s", url);

            Boolean flag = Boolean.FALSE;
            try (Connection conn = DriverManager.getConnection(connectionStr, userName, secretCode)) {
                log.info("Connected to MySQL successfully!");
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT 1");
                if (rs.next()) {
                    log.info("Query executed successfully!");
                }
                rs.close();
                stmt.close();
                conn.close();
                flag = Boolean.TRUE;
            } catch (SQLException e) {
                log.error("Failed to connect to MySQL!", e);
                flag = Boolean.FALSE;
            }
            return flag;
        } else if (dataSourceType.equals("MongoDB")) {
            Boolean flagDB = false;
            // 密码进行encode
            String encodedPassword = URLEncoder.encode(secretCode, StandardCharsets.UTF_8);

            // 构建连接字符串，包含认证信息
            String connectionString = String.format("mongodb://%s:%s@%s/%s?authSource=admin",
                userName, encodedPassword, url, dataSourceName);

            try (MongoClient mongoClient = MongoClients.create(connectionString)) {
                MongoDatabase datasource = mongoClient.getDatabase(dataSourceName);

                Document pingResponse = datasource.runCommand(new Document("ping", 1));
                Object okObj = pingResponse.get("ok");

                if (okObj instanceof Double && okObj.equals(1.0)) {
                    flagDB = Boolean.TRUE;
                }

            } catch (Exception e) {
                log.error("Failed to connect to MongoDB!", e);
                flagDB = Boolean.FALSE;

            }
            return flagDB;
        } else {
            throw new BaseException("数据库不存在，请确认后重试！");
        }
    }
}
